import pandas as pd
import numpy as np
import h5py
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.python.framework import ops
# from tf_utils import *
import time
from tensorflow import keras
# from tensorflow.keras import layers
from tensorflow.keras.layers import Dense,Dropout,Activation,Conv1D,MaxPooling1D,Flatten
from tensorflow.keras.models import Sequential
from tensorflow.keras.utils import to_categorical
import os
import itertools
from sklearn.metrics import confusion_matrix


class LossHistory(keras.callbacks.Callback):
    # 写一个LossHistory类，保存loss和acc
    def on_train_begin(self, logs={}):
        self.losses = {'batch':[], 'epoch':[]}
        self.accuracy = {'batch':[], 'epoch':[]}
        self.val_loss = {'batch':[], 'epoch':[]}
        self.val_acc = {'batch':[], 'epoch':[]}

    def on_batch_end(self, batch, logs={}):
        self.losses['batch'].append(logs.get('loss'))
        self.accuracy['batch'].append(logs.get('acc'))
        self.val_loss['batch'].append(logs.get('val_loss'))
        self.val_acc['batch'].append(logs.get('val_acc'))

    def on_epoch_end(self, batch, logs={}):
        self.losses['epoch'].append(logs.get('loss'))
        self.accuracy['epoch'].append(logs.get('acc'))
        self.val_loss['epoch'].append(logs.get('val_loss'))
        self.val_acc['epoch'].append(logs.get('val_acc'))

    def loss_plot(self, loss_type):
        iters = range(len(self.losses[loss_type]))
        plt.figure()
        # acc
        plt.plot(iters, self.accuracy[loss_type], 'r', label='train acc')
        # loss
        plt.plot(iters, self.losses[loss_type], 'g', label='train loss')
        if loss_type == 'epoch':
            # val_acc
            plt.plot(iters, self.val_acc[loss_type], 'b', label='val acc')
            # val_loss
            plt.plot(iters, self.val_loss[loss_type], 'k', label='val loss')
        plt.grid(True)
        plt.xlabel(loss_type)
        plt.ylabel('acc-loss')
        plt.legend(loc="upper right")
        plt.show()

def mymodel(input_shape):
    model = Sequential()
    model.add(Conv1D(filters=7, kernel_size=5, padding='same', input_shape=input_shape))
    model.add(Conv1D(filters=1, kernel_size=5, padding='same'))
    model.add(Flatten())
    model.add(Dense(7, activation='softmax', name="predictions"))
    history = LossHistory()
    model.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    return model, history
def mymodel_old(input_shape):
    model = Sequential()
    model.add(Dense(20, activation="relu", name="dense_1", input_shape=input_shape))
    # model.add(Dropout(dropout1))
    model.add(Dense(40, activation="relu", name="dense_2"))
    # model.add(Dropout(dropout2))
    model.add(Dense(40, activation="relu", name="dense_3"))
    # model.add(Dropout(dropout2))
    model.add(Dense(7, activation="relu", name="dense_4"))
    model.add(Dense(7, activation="softmax", name="predictions"))
    # history = LossHistory()
    model.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    return model


def get_data(datatype):
    if datatype == 'all_features':
        df0 = pd.read_csv('result_video_images_0_xyz.csv')
        df1 = pd.read_csv('result_video_images_1_xyz.csv')
        df2 = pd.read_csv('result_video_images_2_xyz.csv')
        df3 = pd.read_csv('result_video_images_3_xyz.csv')
        df4 = pd.read_csv('result_video_images_4_xyz.csv')
        df5 = pd.read_csv('result_video_images_5_xyz.csv')
        df6 = pd.read_csv('result_video_images_6_xyz.csv')
        frames = [df0, df1, df2,  df3, df4, df5,  df6]
        train_data = pd.concat(frames)
        train_data = train_data.sample(frac=1)
        dft0=pd.read_csv('result_video_images_test_0_xyz.csv')
        dft1 = pd.read_csv('result_video_images_test_1_xyz.csv')
        dft2 = pd.read_csv('result_video_images_test_2_xyz.csv')
        dft3 = pd.read_csv('result_video_images_test_3_xyz.csv')
        dft4 = pd.read_csv('result_video_images_test_4_xyz.csv')
        dft5 = pd.read_csv('result_video_images_test_5_xyz.csv')
        dft6=pd.read_csv('result_video_images_test_6_xyz.csv')
        dft7=pd.read_csv('result_all_images_xyz.csv')
        framest = [dft0, dft1, dft2, dft3, dft4, dft5, dft6,dft7]
        test_data = pd.concat(framest)
        test_data = test_data.sample(frac=1)
    # elif datatype == 'dist_feature':
    #     df0 = pd.read_csv('result_video_images_0_xyz_feature.csv')
    #     df1 = pd.read_csv('result_video_images_1_xyz_feature.csv')
    #     df2 = pd.read_csv('result_video_images_2_xyz_feature.csv')
    #     df3 = pd.read_csv('result_video_images_3_xyz_feature.csv')
    #     df4 = pd.read_csv('result_video_images_4_xyz_feature.csv')
    #     df5 = pd.read_csv('result_video_images_5_xyz_feature.csv')
    #     df6 = pd.read_csv('result_video_images_6_xyz_feature.csv')
    #     frames = [df0,df1, df2,  df3, df4, df5, df6]
    #     train_data = pd.concat(frames)
    #     train_data = train_data.sample(frac=1)
    #
    #     test_csv = 'result_all_images_xyz_feature.csv'
    #     test_data = pd.read_csv(test_csv)
    # else:
    #     print('undefined datatype!! \n datatype should in [all_features,dist_feature]')
    return train_data,test_data

# 混淆矩阵定义
def plot_confusion_matrix(cm, classes,figname,title='Confusion matrix',cmap=plt.cm.jet):
    cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
    plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks,('0','1','2','3','4','5','6'))
    plt.yticks(tick_marks,('0','1','2','3','4','5','6'))
    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, '{:.2f}'.format(cm[i, j]), horizontalalignment="center",color="white" if cm[i, j] > thresh else "black")
    plt.tight_layout()
    plt.ylabel('真实类别')
    plt.xlabel('预测类别')
    plt.savefig(figname, dpi=200, bbox_inches='tight', transparent=False)
    plt.show()


# 显示混淆矩阵
def plot_confuse(model, x_val, y_val,figname):
    predictions = model.predict_classes(x_val)
    truelabel = y_val.argmax(axis=-1)  # 将one-hot转化为label
    conf_mat = confusion_matrix(y_true=truelabel, y_pred=predictions)
    plt.figure()
    plot_confusion_matrix(conf_mat, range(np.max(truelabel) + 1), figname=figname)
